package com.craftplay.controller;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.craftplay.common.ServerResponse;
import com.craftplay.common.WxMpInfo;
import com.craftplay.configuration.TxSignature;
import com.craftplay.dao.ClassOrderMapper;
import com.craftplay.dao.OrderMapper;
import com.craftplay.model.*;
import com.craftplay.service.*;
import com.craftplay.util.CraftPlayUtil;
import com.craftplay.util.DateUtils;
import com.github.binarywang.wxpay.bean.request.BaseWxPayRequest;
import com.github.binarywang.wxpay.bean.request.WxPayUnifiedOrderRequest;
import com.github.binarywang.wxpay.service.WxPayService;
import com.qcloud.vod.model.VodUploadResponse;
import com.tencentcloudapi.common.Credential;
import com.tencentcloudapi.vod.v20180717.models.DescribeMediaInfosRequest;
import com.tencentcloudapi.vod.v20180717.models.DescribeMediaInfosResponse;
import me.chanjar.weixin.common.api.WxConsts;
import me.chanjar.weixin.common.bean.WxJsapiSignature;
import me.chanjar.weixin.common.bean.menu.WxMenu;
import me.chanjar.weixin.common.bean.menu.WxMenuButton;
import me.chanjar.weixin.common.error.WxErrorException;
import me.chanjar.weixin.mp.api.WxMpMenuService;
import me.chanjar.weixin.mp.api.WxMpQrcodeService;
import me.chanjar.weixin.mp.api.WxMpService;
import me.chanjar.weixin.mp.bean.kefu.WxMpKefuMessage;
import me.chanjar.weixin.mp.bean.result.WxMpOAuth2AccessToken;
import me.chanjar.weixin.mp.bean.result.WxMpQrCodeTicket;
import me.chanjar.weixin.mp.bean.result.WxMpUser;
import me.chanjar.weixin.mp.builder.kefu.NewsBuilder;
import org.apache.commons.codec.binary.Hex;
import org.apache.commons.lang3.StringUtils;
import org.dom4j.DocumentException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;
import com.tencentcloudapi.vod.v20180717.VodClient;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;
import java.net.URLEncoder;
import java.security.MessageDigest;
import java.util.*;

@Controller
@RequestMapping("/play/weixin")

public class WechatController {
    private static final Logger logger = LoggerFactory.getLogger(WechatController.class);
    @Autowired
    private WxMpService wxMpService;


    @Autowired
    HostHolder hostHolder;

    @Autowired
    UserService userService;

    @Autowired
    RecommendService recommendService;

    @Autowired
    TxCloudService txCloudService;

    @Autowired
    private WxPayService wxService;

    @Autowired
    MomentService momentService;

    @Autowired
    private OrderMapper orderMapper;

    @Autowired
    private OrderService orderService;

    @Autowired
    private WeixinService weixinService;

    @Autowired
    private ClassOrderMapper classOrderMapper;


    @RequestMapping(method = RequestMethod.GET, value = "/authorize")
    public String authorize(@RequestParam("returnUrl") String returnUrl) {
        //String url = "http://craftpaly.natapp1.cc/weixin/userInfo";
        String url = "http://playpro.live/play/weixin/userInfo";
        String redirectUrl = wxMpService.oauth2buildAuthorizationUrl(url, WxConsts.OAuth2Scope.SNSAPI_USERINFO, URLEncoder.encode(returnUrl));

        return "redirect:" + redirectUrl;
    }

    @RequestMapping(method = RequestMethod.GET, value = "/userInfo")
    public String userInfo(@RequestParam("code") String code,
                           @RequestParam("state") String returnUrl, HttpServletResponse response) {

        WxMpUser wxMpUser = null;

        WxMpOAuth2AccessToken wxMpOAuth2AccessToken = new WxMpOAuth2AccessToken();
        WxMpOAuth2AccessToken accessToken;

        try {
            accessToken = this.wxMpService.oauth2getAccessToken(code);
            wxMpUser = this.wxMpService.getUserService().userInfo(accessToken.getOpenId(), null);
        } catch (WxErrorException e) {

            e.printStackTrace();
        }


        Map<String, String> map = userService.checkUserInfo(wxMpUser);
        if (map.containsKey("ticket")) {
            Cookie cookie = new Cookie("ticket", map.get("ticket"));
            cookie.setPath("/");
            cookie.setMaxAge(3600 * 24 * 5);
            response.addCookie(cookie);
        }

        return "redirect:" + returnUrl;// + "?openid=" + openId;

    }


    @RequestMapping(method = {RequestMethod.GET, RequestMethod.POST}, value = "/auth")
    public void auth(HttpServletRequest request, HttpServletResponse response) throws DocumentException, IOException {
        try {
            boolean isGet = request.getMethod().toLowerCase().equals("get");
            if (isGet) {
                // 开发者提交信息后，微信服务器将发送GET请求到填写的服务器地址URL上，GET请求携带参数
                String signature = request.getParameter("signature");// 微信加密签名（token、timestamp、nonce。）
                String timestamp = request.getParameter("timestamp");// 时间戳
                String nonce = request.getParameter("nonce");// 随机数
                String echostr = request.getParameter("echostr");// 随机字符串
                // 将token、timestamp、nonce三个参数进行字典序排序
                String[] params = new String[]{WxMpInfo.TOKEN, timestamp, nonce};
                Arrays.sort(params);
                // 将三个参数字符串拼接成一个字符串进行sha1加密
                String clearText = params[0] + params[1] + params[2];
                String algorithm = "SHA-1";
                String sign = new String(
                        Hex.encodeHex(MessageDigest.getInstance(algorithm).digest((clearText).getBytes()), true));
                // 开发者获得加密后的字符串可与signature对比，标识该请求来源于微信
                if (signature.equals(sign)) {

                    response.getWriter().print(echostr);
                }
            } else {
                Map<String, String> map = CraftPlayUtil.parseRequestXmlToMap(request);
                if (map.get("Event").equals("subscribe")) {
                    System.out.println("关注事件");
                    String eventKey = map.get("EventKey");
                    if (eventKey.length() != 0) {
                        int userId = Integer.parseInt(eventKey.substring(8));
                        String openId = map.get("FromUserName");
                        Recommend recommend = recommendService.selectByOpenId(openId);
                        if (recommend == null) {
                            recommend = new Recommend();
                            recommend.setUserId(userId);
                            recommend.setOpenId(openId);
                            recommendService.insertOneRecord(recommend);
                        }
                    }

                    List<Content> subscribeList = recommendService.getContent("subscribe");
                    NewsBuilder fromUserName = WxMpKefuMessage.NEWS().toUser(map.get("FromUserName"));
                    for (Content content : subscribeList) {
                        WxMpKefuMessage.WxArticle article = new WxMpKefuMessage.WxArticle();
                        article.setUrl(content.getUrl());
                        article.setPicUrl(content.getPicUrl());
                        article.setDescription(content.getContent());
                        article.setTitle(content.getTitle());
                        fromUserName.addArticle(article);
                    }
                    WxMpKefuMessage message = fromUserName.build();
                    wxMpService.getKefuService().sendKefuMessage(message);
                    userService.updateSubscribeByOpenId(map.get("FromUserName"), 1);
                } else if (map.get("Event").equals("unsubscribe")) {
                    userService.updateSubscribeByOpenId(map.get("FromUserName"), 0);
                    System.out.println("取消关注");
                } else if (map.get("Event").equals("CLICK")) {
                    String eventKey = map.get("EventKey");
                    if (eventKey.equals("joinGroup")) {
                        WxMpKefuMessage message = WxMpKefuMessage
                                .IMAGE()
                                .toUser(map.get("FromUserName"))
                                .mediaId("LcA4N8L6u2gePfZX8SPqnaFGj-gZAsVNH5rHL6v3ut0")
                                .build();
                        wxMpService.getKefuService().sendKefuMessage(message);
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @RequestMapping(method = RequestMethod.GET, value = "/sign")
    @ResponseBody
    public ServerResponse<WxJsapiSignature> getSign(@RequestParam("url") String url) throws WxErrorException {
        WxJsapiSignature wxJsapiSignature = wxMpService.createJsapiSignature(url);
        return ServerResponse.createBySuccess(wxJsapiSignature);
    }

    @RequestMapping(method = RequestMethod.GET, value = "/qrcode")
    @ResponseBody
    public String getQRCode() throws WxErrorException {
        User user = hostHolder.getUser();
        WxMpQrcodeService wxMpQrcodeService = wxMpService.getQrcodeService();
        if (user != null) {
            WxMpQrCodeTicket wxMpQrCodeTicket = wxMpQrcodeService.qrCodeCreateTmpTicket(user.getUserId(), 2592000);
            String ticket = wxMpQrCodeTicket.getTicket();
            String qrCodeUrl = wxMpQrcodeService.qrCodePictureUrl(ticket);
            return qrCodeUrl;
        } else {
            return "未获取到用户信息";
        }

    }


    @RequestMapping(method = RequestMethod.GET, value = "/last_qrcode")
    @ResponseBody
    public String getLastQRCode() throws WxErrorException {
        User user = hostHolder.getUser();
        WxMpQrcodeService wxMpQrcodeService = wxMpService.getQrcodeService();
        if (user != null) {
            WxMpQrCodeTicket wxMpQrCodeTicket = wxMpQrcodeService.qrCodeCreateLastTicket(user.getUserId());
            String ticket = wxMpQrCodeTicket.getTicket();
            String qrCodeUrl = wxMpQrcodeService.qrCodePictureUrl(ticket);
            return qrCodeUrl;
        } else {
            return "未获取到用户信息";
        }

    }


    @RequestMapping(method = RequestMethod.GET, value = "/getFederationToken")
    @ResponseBody
    public String GetFederationToken() {
        return txCloudService.GetFederationToken();
    }

    /**
     * 腾讯云签名
     *
     * @return
     */
    @RequestMapping(method = RequestMethod.GET, value = "/getTXCloudSign")
    @ResponseBody
    public ServerResponse getTXCloudSign() {
        TxSignature sign = new TxSignature();
        sign.setCurrentTime(System.currentTimeMillis() / 1000);
        sign.setRandom(new Random().nextInt(java.lang.Integer.MAX_VALUE));
        sign.setSignValidDuration(3600 * 24 * 2);

        try {
            String signature = sign.getUploadSignature();
            System.out.println("signature : " + signature);
            return ServerResponse.createBySuccess(signature);
        } catch (Exception e) {
            System.out.print("获取签名失败");
            e.printStackTrace();
        }
        return ServerResponse.createByErrorMessage("获取签名失败");
    }


    /**
     * 获取视频信息
     *
     * @return
     */
    @RequestMapping(method = RequestMethod.GET, value = "/getVideoInfo")
    @ResponseBody
    public ServerResponse getVideoInfo(@RequestParam("fileId") String fileId) {

        TxSignature sign = new TxSignature();
        try {
            // 实例化一个认证对象，入参需要传入腾讯云账户 secretId，secretKey
            Credential cred = new Credential(sign.getSecretId(), sign.getSecretKey());

            // 实例化要请求产品（以 CVM 为例）的 client 对象
            VodClient client = new VodClient(cred, "ap-guangzhou");

            // 实例化一个请求对象
            DescribeMediaInfosRequest req = new DescribeMediaInfosRequest();
            String[] FileIds = {fileId};
            req.setFileIds(FileIds);
            // 通过 client 对象调用想要访问的接口，需要传入请求对象
            DescribeMediaInfosResponse describeMediaInfosResponse = client.DescribeMediaInfos(req);
            // 输出 JSON 格式的字符串回包
            return ServerResponse.createBySuccess(describeMediaInfosResponse);
        } catch (Exception e) {
            System.out.println(e.toString());
        }
        return ServerResponse.createByErrorMessage("获取视频信息");
    }


    /**
     * 腾讯支付
     *
     * @return
     */
    @RequestMapping(method = RequestMethod.POST, value = "/getWXPay")
    @ResponseBody
    @Transactional
    public ServerResponse<Object> getWXPay(@RequestBody ClassOrder buyClass) {
        User user = hostHolder.getUser();
        if (user == null) return ServerResponse.createByErrorMessage("用户不存在");
        if (buyClass.getUnitId() == null) return ServerResponse.createByErrorMessage("活动Id不能为空");
        Unit unit = momentService.oneMomentDetail(buyClass.getUnitId());
        Order myOrder = new Order();
        Integer money;
        if (unit == null) return ServerResponse.createByErrorMessage("活动不存在");


        logger.info(JSON.toJSONString(buyClass));

        //课程
        if (unit.getKind() == 12) {
            if (buyClass.getClassTreeType() == null) return ServerResponse.createByErrorMessage("上课方式不能为空");
            if (buyClass.getMessage() == null) {
                buyClass.setMessage("");
            }
            if (StringUtils.isEmpty(user.getTel())) return ServerResponse.createByErrorMessage("电话未认证");

            //查询是否已经付费
            if (classOrderMapper.isPay(user.getUserId(), unit.getId()) > 1) {
                return ServerResponse.createByErrorMessage("已经支付");
            }
            myOrder.setClassTreeType(buyClass.getClassTreeType());
            myOrder.setClassType(unit.getClassType());

            //价格
            String[] split = unit.getClassMoney().split(",");
            String calssMoney;
            if (split.length > 0) {
                calssMoney = split[buyClass.getClassTreeType() - 1];
            } else {
                calssMoney = unit.getClassMoney();
            }
            money = BaseWxPayRequest.yuanToFen(String.valueOf(calssMoney));

        } else {
            if (unit.getPaySee() != 1) return ServerResponse.createByErrorMessage("不需要付费");

            //查询是否已经付费
            if (orderService.isPay(user.getUserId(), unit.getId())) return ServerResponse.createByErrorMessage("已经支付");
            money = BaseWxPayRequest.yuanToFen(String.valueOf(unit.getPayMoney()));
            myOrder.setMoney(money);
        }

        //订单号
        Date nowTime = new Date();
        String outTradeNo = "JW" + (nowTime.getTime()) + user.getUserId();

        try {
            WxPayUnifiedOrderRequest orderRequest = new WxPayUnifiedOrderRequest();
            orderRequest.setBody("匠玩");
            orderRequest.setOutTradeNo(outTradeNo);
            orderRequest.setTotalFee(money);//元转成分
            orderRequest.setOpenid(user.getOpenId());
            orderRequest.setSpbillCreateIp("192.168.0.104");
            orderRequest.setTimeStart(DateUtils.dateToSpecalString(nowTime));
            orderRequest.setTimeExpire(DateUtils.dateToSpecalString(DateUtils.addSubDay(nowTime, 1)));
            Object order = this.wxService.createOrder(orderRequest);

            myOrder.setCreatetime(nowTime);
            myOrder.setOuttradeno(outTradeNo);
            myOrder.setStatus(1);
            myOrder.setMoney(money);
            myOrder.setUnitid(unit.getId());
            myOrder.setUserid(user.getUserId());
            myOrder.setMessage(buyClass.getMessage() == null ? "" : buyClass.getMessage());
            orderMapper.insert(myOrder);

            return ServerResponse.createBySuccess(order);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return ServerResponse.createByErrorMessage("订单创建失败");
    }


    /**
     * 下载素材并保存到腾讯云
     *
     * @return
     */
    @RequestMapping(method = RequestMethod.GET, value = "/downloadWxAndUpload")
    @ResponseBody
    @Transactional
    public ServerResponse<Object> downloadWxAndUpload(@RequestParam("mediaId") String mediaId) {
        User user = hostHolder.getUser();
        if (user == null) return ServerResponse.createByErrorMessage("用户不存在");
        try {
            File file = wxMpService.getMaterialService().mediaDownload(mediaId);
            VodUploadResponse vodUploadResponse = txCloudService.VodUploadClient(file.getPath());
            return ServerResponse.createBySuccess(vodUploadResponse);
        } catch (Exception e) {
            System.out.println("获取文件失败");
            e.printStackTrace();
        }
        return ServerResponse.createByErrorMessage("上传文件失败");
    }


    @RequestMapping(method = RequestMethod.GET, value = "/menu")
    @ResponseBody
    public String createMenu() throws WxErrorException {
        WxMpMenuService wxMpMenuService = wxMpService.getMenuService();
        if (wxMpMenuService != null) {

            WxMenu wxMenu = new WxMenu();


            WxMenuButton firstMenuButton = new WxMenuButton();
            firstMenuButton.setType(WxConsts.MenuButtonType.CLICK);
            firstMenuButton.setName("加入群组");
            firstMenuButton.setKey("joinGroup");

            WxMenuButton secondMenuButton = new WxMenuButton();
            secondMenuButton.setType("view");
            secondMenuButton.setUrl("http://playpro.live/index.html#/tech/indecate");
            secondMenuButton.setName("不吝指教");


            WxMenuButton threeMenuButton = new WxMenuButton();
            threeMenuButton.setType("view");
            threeMenuButton.setName("我的匠玩");
            threeMenuButton.setKey("mycraft");
            threeMenuButton.setUrl("http://playpro.live/index.html#/wdjw/my");

            List<WxMenuButton> firstMenuButtons = new ArrayList();
            firstMenuButtons.add(firstMenuButton);
            firstMenuButtons.add(secondMenuButton);
            firstMenuButtons.add(threeMenuButton);

            wxMenu.setButtons(firstMenuButtons);
            String str = wxMpMenuService.menuCreate(wxMenu);
            if (str == null) {
                return "Create Success!";
            } else {
                return "Create Failed!";
            }

        } else {
            return "未获取到用户信息";
        }
    }


}
